"use strict";

//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------

const assert = require("chai").assert;
const Traverser = require("../../../lib/shared/traverser");

//------------------------------------------------------------------------------
// Tests
//------------------------------------------------------------------------------

describe("Traverser", () => {
	it("traverses all keys except 'parent', 'leadingComments', and 'trailingComments'", () => {
		const traverser = new Traverser();
		const fakeAst = {
			type: "Program",
			body: [
				{
					type: "ExpressionStatement",
					leadingComments: {
						type: "Line",
					},
					trailingComments: {
						type: "Block",
					},
				},
				{
					type: "FooStatement",
					foo: {
						type: "BarStatement",
					},
				},
			],
		};

		fakeAst.body[0].parent = fakeAst;

		const enteredNodes = [];
		const exitedNodes = [];

		traverser.traverse(fakeAst, {
			enter: node => enteredNodes.push(node),
			leave: node => exitedNodes.push(node),
		});

		assert.deepStrictEqual(enteredNodes, [
			fakeAst,
			fakeAst.body[0],
			fakeAst.body[1],
			fakeAst.body[1].foo,
		]);
		assert.deepStrictEqual(exitedNodes, [
			fakeAst.body[0],
			fakeAst.body[1].foo,
			fakeAst.body[1],
			fakeAst,
		]);
	});

	it("traverses AST as using 'visitorKeys' option if given", () => {
		const traverser = new Traverser();
		const fakeAst = {
			type: "Program",
			body: [
				{
					type: "ClassDeclaration",
					id: {
						type: "Identifier",
					},
					superClass: null,
					body: {
						type: "ClassBody",
						body: [],
					},
					experimentalDecorators: [
						{
							type: "Decorator",
							expression: {},
						},
					],
				},
			],
		};

		fakeAst.body[0].parent = fakeAst;

		const visited = [];

		// with 'visitorKeys' option to traverse decorators.
		traverser.traverse(fakeAst, {
			enter: node => visited.push(node.type),
			visitorKeys: Object.assign({}, Traverser.DEFAULT_VISITOR_KEYS, {
				ClassDeclaration:
					Traverser.DEFAULT_VISITOR_KEYS.ClassDeclaration.concat([
						"experimentalDecorators",
					]),
			}),
		});
		assert.deepStrictEqual(visited, [
			"Program",
			"ClassDeclaration",
			"Identifier",
			"ClassBody",
			"Decorator",
		]);
	});
});
